<?php

/*
CakePHP Upload Component :: Upload
Version     : 1.0
Author      : hduongdmit@gmail.com
Website     : http://www.gaothaibinh.com
Created     : 20/04/2014
compatible  : cakePHP2.x

Description	:
This Component is used to upload image in cakePHP.

*/
App::uses('Component', 'Controller');
class UploadComponent extends Component
{

	const ERROR_NO_FILE_UPLOAD = 'No file upload ';
	const ERROR_FILE_SIZE_UPLOAD = 'Error file size upload bigger, must less than: ';
	const ERROR_FILE_EXTENSION_UPLOAD = 'Error extension file upload, only support: ';

	/*
	 * variables (self explanatory)
	* */
	private $allowedExtensions = array();

	/* the size limit by default is basicaly 1 MB = 1 * 1024 * 1024
	 * so if you want to change it while loading this component instantiate it with the value of your choice x MB = x * 1024 *1024
	* */
	private $sizeLimit = 10485760;

	private $resizeBigImage = array();
	private $resizeSmallImage = array();
	private $resizeThumbImage = array();

	/*
	 * filename is a string
	* */
	private $filename = null;
	private $ext      = null;
	private $error    = null;
	private $folderUpload   = null;


	//called before Controller::beforeFilter()
	public function __construct(ComponentCollection $collection, $settings = array()) {
		parent::__construct($collection, $settings);
	}

	/**
	 * Called before the Controller::beforeFilter().
	 *
	 * @param Controller $controller Controller with components to initialize
	 * @return void
	 * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::initialize
	 */
	public function initialize(Controller $controller) {
		$this->controller = $controller;

		$config = Configure::read('upload_image');
		$this->allowedExtensions =  array_map("strtolower", $config['extensions']);
		$this->sizeLimit = $config['sizeLimit'];
		$this->resizeBigImage = isset($config['big']) ? $config['big'] : '';
		$this->resizeSmallImage = isset($config['small']) ? $config['small'] : '';
		$this->resizeThumbImage = isset($config['thumb']) ? $config['thumb'] : '';

		$this->folderUpload = 'uploads/'. date('Y/md/');
	}

	/**
	 * Upload image
	 * @param array $formData
	 * @param string $folder
	 * @return array
	 */
	public function uploadImage($formData = array(), $resize = true){

		$filename = '';
		$error = '';
		$folder = $this->folderUpload;
		//check extension
		if (self::checkUploadExtension($formData['name'])){
			//generate name
			$this->filename = self::generateName($formData['name']);
			$this->ext      = self::getExtension($formData['name']);
			// create the folder if it does not exist
			if(!is_dir($folder)) {
				mkdir($folder, 0755, true);
			}

			// upload the file
			move_uploaded_file($formData['tmp_name'], $folder . $this->filename.$this->ext);
			//resize image
			if ($resize) self::resizeImage($folder, $this->filename);
		} else {
			$this->error = self::ERROR_FILE_EXTENSION_UPLOAD . implode(', ', $this->allowedExtensions);
			return;
		}
	}

	/**
	 * write text to image
	 *
	 * @param string $folder
	 * @param string $filename
	 * @param string $text
	 * @param string $coordinatesX
	 * @param string $coordinatesY
	 */
	public function writeTextToImage($folder = '', $filename = '', $text = '', $coordinatesX = 'center', $coordinatesY = 'center'){
		$image = WideImage::load($folder . $filename);
		$canvas = $image->getCanvas();
		$canvas->useFont('path/to/arial.ttf', 16, $image->allocateColor(0, 0, 0));
		$canvas->writeText($coordinatesX, $coordinatesY, $text);
		$image->saveToFile($folder . $filename);
	}

	/**
	 * merge logo to image
	 *
	 * @param string $picImage
	 * @param string $logoImage
	 * @param string $coordinatesX
	 * @param string $coordinatesY
	 * @param number $opacity
	 */
	public function addLogoToImage($picImage = '', $logoImage = '', $coordinatesX = 'center', $coordinatesY = 'center', $opacity = 30){
		$img = WideImage::load($picImage);
		$watermark = WideImage::load($logoImage);

		$new = $img->merge($watermark, $coordinatesX, $coordinatesY, $opacity);

	}

	/**
	 * get file name
	 * @return string filename
	 */
	public function getFileName(){
		return date('Y/md/').$this->filename.$this->ext;
	}

	/**
	 * get error
	 * @return string error
	 */
	public function error(){
		return $this->error;
	}

	/**
	 * Resize upload image
	 * @param string $folder
	 * @param string $filename
	 */
	private function resizeImage($folder = '', $filename = ''){
		if ($filename != ''){
			$image = WideImage::load($folder . $filename . $this->ext);
			if ($this->resizeBigImage && $this->resizeBigImage[0] == true){
				$resized = $image->resize($this->resizeBigImage[1], $this->resizeBigImage[2]);
				$resized->saveToFile($folder . $filename .'-big'. $this->ext);
			}

			if ($this->resizeSmallImage && $this->resizeSmallImage[0] == true){
				$resized = $image->resize($this->resizeSmallImage[1], $this->resizeSmallImage[2]);
				$resized->saveToFile($folder . $filename .'-small'. $this->ext);
			}

			if ($this->resizeThumbImage && $this->resizeThumbImage[0] == true){
				$resized = $image->resize($this->resizeThumbImage[1], $this->resizeThumbImage[2]);
				$resized->saveToFile($folder . $filename .'-thumb'. $this->ext);
			}
		}

	}

	/**
	 * check upload image
	 * @param array $formData
	 * @return boolean
	 */
	public function isUploadedFile($formData = array()) {
		return is_uploaded_file($formData['tmp_name']);
	}

	/**
	 * Generate image name
	 * @param string $fileName
	 * @return string
	 */
	private function generateName($filename = ''){
		$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
		$name = '';
		for ($i = 0; $i < 5; $i++) {
			$name .= $characters[rand(0, strlen($characters) - 1)];
		}

// 		$ext = substr($filename, (strrpos($filename, ".") + 1));
		$filename = substr($filename, 0, -4);

// 		return date('Ymds') .'-'. $filename .'.' . $ext;
		return $filename .'-'. $name;
	}


	/**
	 * Get extension file
	 * @param string $filename
	 * @return string
	 */
	private function getExtension($filename){
		return '.'. substr($filename, (strrpos($filename, ".") + 1));
	}

	/**
	 * Check upload file extension
	 * @param string $fileName
	 * @return boolean
	 */
	private function checkUploadExtension($filename = ''){

		$allowedExtensions = $this->allowedExtensions;
		$sExtension = substr( $filename, ( strrpos($filename, '.') + 1 ) );
		$sExtension = strtolower($sExtension);

		$pass = false;
		for ($i = 0; $i < count($allowedExtensions); $i++){
			if ($sExtension == $allowedExtensions[$i]) $pass = true;
		}

		return $pass;
	}

	/**
	 * Check file size upload
	 * @param string $fileName
	 * @return boolean
	 */
	private function checkFileSize($filename = ''){
		if (filesize($filename) > $this->sizeLimit){
			return false;
		}

		return true;
	}

	/**
	 *
	 * @param unknown $bytes
	 * @return string
	 */
	private function formatBytes($bytes) {
		if ($bytes < 1024) return $bytes.' B';
		elseif ($bytes < 1048576) return round($bytes / 1024, 2).' KB';
		elseif ($bytes < 1073741824) return round($bytes / 1048576, 2).' MB';
		elseif ($bytes < 1099511627776) return round($bytes / 1073741824, 2).' GB';
		else return round($bytes / 1099511627776, 2).' TB';
	}
}
